package com.y.fund.aacore.dao;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.lang3.ObjectUtils;
import org.hibernate.CacheMode;
import org.hibernate.NonUniqueResultException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.query.MutationQuery;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.Query;
import org.hibernate.query.SelectionQuery;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.y.fund.aacore.able.Idable;
import com.y.fund.aacore.able.TimeCreateable;
import com.y.fund.aacore.able.TimeEditable;
import com.y.fund.aacore.abs.OperObj;
import com.y.fund.aacore.data.NewDataCodeParam;
import com.y.fund.aacore.data.PaginationList;
import com.y.fund.aacore.vo.IdVersionVo;
import com.y.fund.aacore.vo.PagingVo;
import com.y.fund.domain.com.CO11DataCode;
import com.y.fund.handler.CurrLgnUserVo;
import com.y.fund.utils.DateTimeUtil;
import com.y.fund.utils.IdGenerator;
import com.y.fund.utils.ReflectUtil;
import com.y.fund.utils.SQLUtil;
import com.y.fund.utils.StrUtil;
import com.y.fund.web.aavo.com.LgnUserVo;

import jakarta.persistence.Entity;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Transient;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.Selection;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Repository("baseDAO")
public class BaseDAO {

	protected final static Set<String> UpdtJpaKeys = new HashSet<String>();

	static {
		UpdtJpaKeys.add("id");
		UpdtJpaKeys.add("version");
		UpdtJpaKeys.add("createTime");
	}

	final static String NewCodeSql = "insert into CO00_DATA_CODE(id, D_VERSION, BIZ_ID, DATA_MODEL, TIME_RANGE, NUM_VAL)"
			+ "values(:id,0, :bizId, :dataModel, :timeRange, 1+(select nvl(max(dc.NUM_VAL), 0) from CO00_DATA_CODE dc where dc.DATA_MODEL=:dataModel and dc.TIME_RANGE=:timeRange))";

	
	public BaseDAO() {}

	@Getter
	@Autowired
	@Qualifier("masterSessionFactory")
	private SessionFactory sessionFactory;

	@Getter
	@PersistenceContext
	EntityManager entityManager;
	

	public Session getCurrSession() throws DataAccessException {
		return getEntityManager().unwrap(Session.class);
	}

	public void clearSession() throws DataAccessException {
		Session session = this.getCurrSession();
		session.flush();
		session.clear();
	}

	public Set<Class> getEntitySet() {
		return getEntityManager().getMetamodel().getEntities()
				.stream().map(jakarta.persistence.metamodel.Type::getJavaType).collect(Collectors.toSet());
	}


	/** 为业务数据生成编号  */
	public CO11DataCode newCode(NewDataCodeParam param) {
		if(null == param) {
			param = new NewDataCodeParam();
		}
		String bizId = param.getBizId();
		if(StrUtil.isBlankIncNullStr(bizId)) {
			bizId = IdGenerator.Id32();
		}
		String dataModel = param.getDataModel();
		if(StrUtil.isBlankIncNullStr(dataModel)) {
			dataModel = CO11DataCode.DATA_MODEL_DEF;
		}
		Integer timeRange = param.getTimeRange();
		if(null == timeRange ||timeRange<2000) {
			timeRange = DateTimeUtil.GetYyyyMM(LocalDate.now());
		}

		final String cid = IdGenerator.Id32();


		List<HibernateParam> params = new ArrayList<>();
		params.add(new HibernateParam("id", cid));
		params.add(new HibernateParam("bizId", bizId));
		params.add(new HibernateParam("dataModel", dataModel));
		params.add(new HibernateParam("timeRange", timeRange));

		if(execSQL(NewCodeSql, params) > 0) {
			return findObjById(CO11DataCode.class, cid);
		}

		CO11DataCode cdc = new CO11DataCode();
		cdc.setBizId(bizId);
		cdc.setDataModel(dataModel);
		cdc.setFullCode(cid);
		cdc.setNumVal(new Random().nextInt());
		cdc.setTimeRange(timeRange);
		return cdc;

	}

	public <R> List<R> execuQuery(String sql, Integer pageSize, Integer pageNum, Map<String, Object> params, Class<R> clazz) {
		NativeQuery<R> query = this.getCurrSession().createNativeQuery(sql, clazz);
		for (Map.Entry<String, Object> param : params.entrySet()) {
			query.setParameter(param.getKey(), param.getValue());
		}

		query.setFirstResult((pageNum - 1) * pageSize);
		query.setMaxResults(pageSize);
		query.setCacheMode(CacheMode.IGNORE);
		return query.list();
	}

	/**执行SQL语句,并返回受影响的记录条数 */
	public int execSQL(final String sql, Collection<HibernateParam> params){
		if(StrUtil.isBlankIncNullStr(sql)) {
			return 0;
		}
		Session session = getCurrSession();
		return fillParams(session.createNativeQuery(sql), params).executeUpdate();
	}

	/**使用SQL语句查询记录 */
	public List queryBySQL(final String sql, Collection<HibernateParam> params){
		if(StrUtil.isBlankIncNullStr(sql)) {
			return null;
		}
		Session session = getCurrSession();
		return fillParams(session.createNativeQuery(sql), params).getResultList();
	}

	public Long countBySql(String sql, Map<String, Object> params) {
		NativeQuery query = this.getCurrSession().createNativeQuery(sql);
		for (Map.Entry<String, Object> param : params.entrySet()) {
			query.setParameter(param.getKey(), param.getValue());
		}
		query.setCacheMode(CacheMode.IGNORE);
		BigDecimal count = (BigDecimal) query.getSingleResult();
		return count.longValue();
	}

	
	public int updtByIdIgnoreNullObjs(Collection<? extends Idable> olist) throws DataAccessException {
		if(null==olist || olist.size()<1) {
			return 0;
		}
		int c = 0;
		try{
			for(Idable o : olist) {
				c += updtByIdIgnoreNull(o);
			}
		}catch(Exception nuo){
			nuo.printStackTrace();
		}
		return c;
	}


	/** Update fields in the object whose data is not null  */
	public int updtByIdIgnoreNull(Idable obj) {
		return updtByIdIgnoreNull(true, obj);
	}

	public int updtByIdIgnoreNull(boolean needUpdtVersion, Idable obj) {
		return updtByIdIgnoreNull(needUpdtVersion, obj, true);
	}

	/** 更新对象中数据不为null的字段 */
	public boolean updtByIdIgnoreNull1(Idable obj) {

		if(null==obj || StrUtil.isBlankIncNullStr(obj.getId())) {
			System.err.println("要更新的对象不能为空，id主键不能为空  ");
			return false;
		}
		final Class clz = obj.getClass();

		Entity ety = (Entity) clz.getAnnotation(Entity.class);
		if(null == ety) {
			System.err.println("不能更新非持久化类，持久化类需有@Entity注解  ");
			return false;
		}

		String etyName = ety.name();
		if(StrUtil.isBlankIncNullStr(ety.name())) {
			etyName = clz.getSimpleName();
		}

		Set<Method> mths = ReflectUtil.getPubGetterMethods(clz);
		if(null==mths || mths.size()<1) {
			System.err.println("没有任何公共的getter方法  ");
			return false;
		}
		Map<String, Object> fieldVal = new HashMap<String, Object>();

		try {
			Set<Field> sf = ReflectUtil.getDeclaredFields(clz, true);
			for(Field ff : sf) {
				Transient tr  = ff.getAnnotation(Transient.class);
				if(null != tr) {
					continue;
				}
				if(UpdtJpaKeys.contains(ff.getName())){
					continue;
				}

				String gmName = "get" + ReflectUtil.UpperHeadChar(ff.getName());

				Iterator<Method> mIter = mths.iterator();
				while(mIter.hasNext()) {
					Method m = mIter.next();
					if(gmName.equals(m.getName())) {
						Object val = m.invoke(obj);
						if(null != val) {
							fieldVal.put(ff.getName(), val);
						}
						mIter.remove();
						break;
					}
				}
			}

			if(fieldVal.size() < 1) {
				System.err.println("没有可更新的非空属性值  ");
				return false;
			}

			StringBuffer hql = new StringBuffer();
			hql.append("update ").append(etyName).append(" set version=version+1 ");

			Set<String> fkeySet = fieldVal.keySet();
			List<HibernateParam> params = new ArrayList<HibernateParam>();
			for(String fkey : fkeySet) {
				hql.append(",").append(fkey).append("=:fv_").append(fkey);
				params.add(new HibernateParam("fv_"+fkey,  fieldVal.get(fkey)));
			}
			hql.append(" where id=:fv_id ");
			params.add(new HibernateParam("fv_id", obj.getId()));
			if(null != obj.getVersion()) {
				hql.append(" and version=:fv_version ");
				params.add(new HibernateParam("fv_version", obj.getVersion()));
			}

			execUpdtHql(hql.toString(), params);

			return true;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}



	public int updtByIdIgnoreNullNoLog(Idable obj) {
		return updtByIdIgnoreNull(true, obj, false);
	}

	/** Update fields in the object whose data is not null  */
	public int updtByIdIgnoreNull(boolean needUpdtVersion, Idable obj, boolean needOperlog) {

		if(null==obj || StrUtil.isBlankIncNullStr(obj.getId())) {
			return 0;
		}
		final Class clz = obj.getClass();
		Set<Method> mths = ReflectUtil.getPubGetterMethods(clz);
		if(null==mths || mths.size()<1) {
			return 0;
		}
		Map<String, Object> fieldVal = new HashMap<String, Object>();
		try {
			Set<Field> sf = ReflectUtil.getDeclaredFields(clz, true);
			for(Field ff : sf) {
				Transient tr  = ff.getAnnotation(Transient.class);
				if(null != tr) {
					continue;
				}
				if(UpdtJpaKeys.contains(ff.getName())){
					continue;
				}

				String gmName = "get" + ReflectUtil.UpperHeadChar(ff.getName());

				Iterator<Method> mIter = mths.iterator();
				while(mIter.hasNext()) {
					Method m = mIter.next();
					if(gmName.equals(m.getName())) {
						Object val = m.invoke(obj);
						if(null != val) {
							fieldVal.put(ff.getName(), val);
						}
						mIter.remove();
						break;
					}
				}
			}
			return updtByIdForKeyVal(needUpdtVersion, obj, fieldVal, needOperlog);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}


	/**批量执行SQL语句 */
	public boolean execUpdtSQLs(final Collection<String> sqls){
		if(null==sqls || sqls.size()<1) {
			return false;
		}
		Session session = getCurrSession();
		for(String sql : sqls) {
			int size = session.createNativeQuery(sql).executeUpdate();
			log.info("使用SQL语句更新了 " + size + "数据，执行语句为：" + sql);
		}
		return true;
	}


	/** Update fields in the object whose data is not null  */
	public int updtByIdForKeyVal(boolean needUpdtVersion, Idable obj, Map<String, Object> fieldVals, boolean needOperlog) {

		if(null==obj || StrUtil.isBlankIncNullStr(obj.getId())
				|| null==fieldVals || fieldVals.size()<1) {
			return 0;
		}
		final Class clz = obj.getClass();

		Entity ety = (Entity) clz.getAnnotation(Entity.class);
		if(null == ety) {
			return 0;
		}

		String etyName = ety.name();
		if(StrUtil.isBlankIncNullStr(ety.name())) {
			etyName = clz.getSimpleName();
		}

		Set<Method> mths = ReflectUtil.getPubGetterMethods(clz);
		if(null==mths || mths.size()<1) {
			return 0;
		}
		try {

			StringBuffer hql = new StringBuffer();
			if(needUpdtVersion) {
				hql.append("update ").append(etyName).append(" set version=version+1 ");
			}else {
				hql.append("update ").append(etyName).append(" set version=version ");
			}

			Set<String> fkeySet = fieldVals.keySet();
			List<HibernateParam> params = new ArrayList<HibernateParam>();
			for(String fkey : fkeySet) {
				hql.append(",").append(fkey).append("=:fv_").append(fkey);
				params.add(new HibernateParam("fv_"+fkey,  fieldVals.get(fkey)));
			}
			hql.append(" where id=:fv_id ");
			params.add(new HibernateParam("fv_id", obj.getId()));
			if(null != obj.getVersion()) {
				hql.append(" and version=:fv_version ");
				params.add(new HibernateParam("fv_version", obj.getVersion()));
			}

			MutationQuery query = fillParams(getCurrSession().createMutationQuery(hql.toString()), params);
			if(null != query){
				return query.executeUpdate();
			}else {
				return 0;
			}

		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public <T extends Idable> T findObjByExample(T instance, String [] fieldNames) {
		return findObjByExample(instance, null, fieldNames);
	}

	/**  Find the first object with the same attribute value according to the example  */
	public <T extends Idable> T findObjByExample(final T instance, final LinkedHashMap<String,String> orderMap, String [] fieldNames){
		if(null == instance) {
			return null;
		}

		try {
			if(null==orderMap || orderMap.size()<1) {
				return findUniqueObjByExample(instance, fieldNames);
			}
		}catch(Exception e) {
			if((e instanceof NonUniqueResultException)) {
			}else {
				e.printStackTrace();
				return null;
			}
		}
		List<T> list = findListByExample(instance, 1, orderMap, fieldNames);
		if(null!=list && list.size()>0) {
			T t = list.get(0);
			this.getCurrSession().evict(t);
			return t;
		}
		return null;
	}

	/** 根据示例字段查询属性值相同的数据记录  */
	public <T extends Idable> T findUniqueObjByExample(final T instance, String [] fieldNames) throws DataAccessException{
		if(null == instance){
			return null;
		}

		Session session = getCurrSession();
		
		StringBuffer hql = new StringBuffer(" from ")
				.append(instance.getClass().getCanonicalName()).append(" where 1=1 ");
		
		List<HibernateParam> params = new ArrayList<HibernateParam>();

		// 获取实体中所有属性字段
		Set<Field> fields = ReflectUtil.getDeclaredFields(instance.getClass(), true);
		for (Field field : fields) {
	        // 获取属性字段类型
	   		String canonicalName = field.getType().getCanonicalName();
	   		if(Modifier.isStatic(field.getModifiers())) {
	   			/* 静态变量不作为查询条件 */
	   			continue;
	   		}
	   		 // 获取字段值
	         Object fieldValue = ReflectUtil.getFieldValue(instance, field);
	         if(ObjectUtils.isEmpty(fieldValue)) {
		   		/* 空置不作为查询条件 */
	        	 continue;
	         }

	         params.add(new HibernateParam(field.getName(), fieldValue));
	         hql.append(" and ").append(field.getName()).append("=:").append(field.getName());
	    }
		
		/* 查询实际业务数据 */
		SelectionQuery<?> query = session.createSelectionQuery(hql.toString());
		for(HibernateParam pr : params){
			query.setParameter(pr.getName(), pr.getVal());
		}

		return (T) query.uniqueResult();
	}
	
	public <T extends Idable>List<T> findListByExample(final T instance){
		return findListByExpMatchMode(MatchMode.EXACT, instance, null, null, null);
	}

	public <T extends Idable>List<T> findListByExample(final T instance, Integer maxSize){
		return findListByExpOrder(instance, maxSize, null);
	}

	/**  根据示例对象查找属性值相同的数据列表，可指定最大数据集 */
	public <T extends Idable>List<T> findListByExpOrder(final T instance, Integer maxSize, final LinkedHashMap<String,String> orderMap){
		return findListByExample(instance, maxSize, orderMap, null);
	}

	public <T extends Idable> List<T> findListFieldsByExample(final T instance, String[] fieldNames) {
		return findListByExpMatchMode(MatchMode.EXACT, instance, null, null, fieldNames);
	}

	public <T extends Idable> List<T> findListFieldsByExpLike(final T instance, String[] fieldNames) {
		return findListByExpMatchMode(MatchMode.ANYWHERE, instance, null, null, fieldNames);
	}

	/**  根据示例对象查找属性值相似的数据列表，可指定最大数据集 */
	public <T extends Idable>List<T> findListByExpLike(final T instance, Integer maxSize, final LinkedHashMap<String,String> orderMap){
		return findListByExpMatchMode(MatchMode.ANYWHERE, instance,maxSize, orderMap, null);
	}

	public <T extends Idable>List<T> findListByExample(final T instance, Integer maxSize, final LinkedHashMap<String,String> orderMap, String [] fieldNames){
		return findListByExpMatchMode(MatchMode.EXACT, instance,maxSize, orderMap, fieldNames);
	}
	
	/**
	 * 根据ID及示例对象的非空字段精确匹配查找数据记录
	 */
	public <T extends Idable> List<T> findListByExpAndIdIn(final T instance, Collection idVals, final LinkedHashMap<String, String> orderMap, String[] fieldNames) {
		return findListByExpAndFieldIn(instance, "id", idVals, orderMap, fieldNames);

	}
	
	/** 根据ID及示例对象的非空字段精确匹配查找数据记录  */
	public <T extends Idable>List<T> findListByExpAndFieldIn(final T instance, String fieldName, Collection fieldVals, final LinkedHashMap<String,String> orderMap, String [] fieldNames){
		List<T> list = new ArrayList<T>();
		if(null == instance || StrUtil.isBlankIncNullStr(fieldName) || null==fieldVals || fieldVals.size()<1){
			return list;
		}
		EntityManager em = getEntityManager();
		CriteriaBuilder builder = em.getCriteriaBuilder();

		CriteriaQuery query = builder.createQuery(instance.getClass());
		Root root = query.from(instance.getClass());

		// 获取实体中所有属性字段
		Set<Field> fields = ReflectUtil.getDeclaredFields(instance.getClass(), true);
	    List<Predicate> predicates = new ArrayList<>();
		for (Field field : fields) {
	   		if(Modifier.isStatic(field.getModifiers())) {
	   			/* 静态变量不作为查询条件 */
	   			continue;
	   		}
	   		 // 获取字段值
	         Object fieldValue = ReflectUtil.getFieldValue(instance, field);
	         if(ObjectUtils.isEmpty(fieldValue)) {
		   		/* 空置不作为查询条件 */
	        	 continue;
	         }
	         /** 精确匹配，直接等于模式比对 */
			 predicates.add(builder.equal(root.get(field.getName()), fieldValue));
	    }

		predicates.add(builder.in(root.get(fieldName).in(fieldVals)));
		query.select(root).where(builder.and(predicates.toArray(new Predicate[predicates.size()])));

		list.addAll(em.createQuery(query).getResultList());

		return list;
	}
	
	/** 根据示例数据查找属性值相同的数据记录 */
	public <T extends Idable>List<T> findListByExpMatchMode(MatchMode matchMode, final T instance, Integer maxSize, final LinkedHashMap<String,String> orderMap, String [] fieldNames){
		List<T> list = new ArrayList<T>();
		if(null == instance){
			return list;
		}

		Session session = getCurrSession();

		StringBuffer hql = new StringBuffer(" from ")
				.append(instance.getClass().getCanonicalName()).append(" where 1=1 ");
		
		List<HibernateParam> params = new ArrayList<HibernateParam>();
		
		// 获取实体中所有属性字段
		Set<Field> fields = ReflectUtil.getDeclaredFields(instance.getClass(), true);
				
		if(null==matchMode || MatchMode.EXACT.equals(matchMode)) {
			for (Field field : fields) {
		   		if(Modifier.isStatic(field.getModifiers())) {
		   			/* 静态变量不作为查询条件 */
		   			continue;
		   		}
		   		 // 获取字段值
		         Object fieldValue = ReflectUtil.getFieldValue(instance, field);
		         if(ObjectUtils.isEmpty(fieldValue)) {
			   		/* 空置不作为查询条件 */
		        	 continue;
		         }

		         params.add(new HibernateParam(field.getName(), fieldValue));
		         hql.append(" and ").append(field.getName()).append("=:").append(field.getName());
		    }
		}else{
			for (Field field : fields) {
		        // 获取属性字段类型
		   		if(Modifier.isStatic(field.getModifiers())) {
		   			/* 静态变量不作为查询条件 */
		   			continue;
		   		}
		   		 // 获取字段值
		         Object fieldValue = ReflectUtil.getFieldValue(instance, field);
		         if(ObjectUtils.isEmpty(fieldValue)) {
			   		/* 空置不作为查询条件 */
		        	 continue;
		         }
		         Class ftype = field.getType();
		         if("id".equals(field.getName())) {
			         params.add(new HibernateParam(field.getName(), fieldValue));
			         hql.append(" and ").append(field.getName()).append("=:").append(field.getName());
		         }else if(fieldValue instanceof Number || fieldValue instanceof Boolean){
		        	 params.add(new HibernateParam(field.getName(), matchMode.toMatchString((String)fieldValue)));
		        	 hql.append(" and ").append(field.getName()).append("=:").append(field.getName());
		         }else if(ftype.isPrimitive() || ReflectUtil.BasicDataTypes.contains(ftype)) {
		        	 params.add(new HibernateParam(field.getName(), matchMode.toMatchString((String)fieldValue)));
		        	 hql.append(" and ").append(field.getName()).append(" like :").append(field.getName());
		         }
		         
		         /* 对象类型的参数暂不处理 */		         
		    }
		}
		
		List<String> ostr = new ArrayList();
		if(null!=orderMap && orderMap.size()>0){
			Set<String> pKeys =  orderMap.keySet();
			boolean noId = true;
			for(String propertyName : pKeys){
				if(null!=propertyName && !"".equals(propertyName.trim())){
					if("desc".equalsIgnoreCase(orderMap.get(propertyName))){
						ostr.add(propertyName + " DESC ");
					}else{
						ostr.add(propertyName + " ASC ");
					}
					if("id".equalsIgnoreCase(propertyName)) {
						noId = false;
					}
				}
			}
			if(noId && instance instanceof Idable) {
				ostr.add(" id DESC ");
			}
		}else if(instance instanceof Idable) {
			ostr.add(" id DESC ");
		}

		/* 查询实际业务数据 */
		SelectionQuery query = session.createSelectionQuery(hql.toString() + " order by " + String.join(",", ostr));
		for(HibernateParam pr : params){
			query.setParameter(pr.getName(), pr.getVal());
		}

		if(null==maxSize || maxSize>SQLUtil.MAX_QUERY_SIZE
				|| (maxSize<1 && maxSize!=SQLUtil.UN_LIMIT_SIZE)) {
			query.setFirstResult(0);
			query.setMaxResults(SQLUtil.MAX_QUERY_SIZE);
		}else if(maxSize > 0) {
			query.setFirstResult(0);
			query.setMaxResults(maxSize);
		}
		list.addAll(query.list());

		return list;
	}

	/** 根据示例数据查找第一个匹配的IdVersion字段 */
	public IdVersionVo findIdVersionByExample(final Idable instance, final LinkedHashMap<String,String> orderMap){
		if(null == instance){
			return null;
		}

		Session session = getCurrSession();

		StringBuffer hql = new StringBuffer("select new ").append(IdVersionVo.class.getName()).append("(id, version) from ")
				.append(instance.getClass().getCanonicalName()).append(" where 1=1 ");
		
		List<HibernateParam> params = new ArrayList<HibernateParam>();
		
		// 获取实体中所有属性字段
		Set<Field> fields = ReflectUtil.getDeclaredFields(instance.getClass(), true);

		for (Field field : fields) {
	        // 获取属性字段类型
	   		if(Modifier.isStatic(field.getModifiers())) {
	   			/* 静态变量不作为查询条件 */
	   			continue;
	   		}
	   		 // 获取字段值
	         Object fieldValue = ReflectUtil.getFieldValue(instance, field);
	         if(ObjectUtils.isEmpty(fieldValue)) {
		   		/* 空置不作为查询条件 */
	        	 continue;
	         }
	         params.add(new HibernateParam(field.getName(), fieldValue));
	         hql.append(" and ").append(field.getName()).append("=:").append(field.getName());
	    }
		
		List<String> ostr = new ArrayList();
		if(null!=orderMap && orderMap.size()>0){
			Set<String> pKeys =  orderMap.keySet();
			boolean noId = true;
			for(String propertyName : pKeys){
				if(null!=propertyName && !"".equals(propertyName.trim())){
					if("desc".equalsIgnoreCase(orderMap.get(propertyName))){
						ostr.add(propertyName + " DESC ");
					}else{
						ostr.add(propertyName + " ASC ");
					}
					if("id".equalsIgnoreCase(propertyName)) {
						noId = false;
					}
				}
			}
			if(noId && instance instanceof Idable) {
				ostr.add(" id DESC ");
			}
		}else if(instance instanceof Idable) {
			ostr.add(" id DESC ");
		}

		/* 查询实际业务数据 */
		SelectionQuery query = session.createSelectionQuery(hql.toString() + " order by " + String.join(",", ostr));
		for(HibernateParam pr : params){
			query.setParameter(pr.getName(), pr.getVal());
		}

		query.setFirstResult(0);
		query.setMaxResults(1);
		List<IdVersionVo> ivList  = query.list();

		return (null!=ivList && ivList.size()>0)?ivList.get(0):null;
	}

	/**  根据样例数据查询相同属性值的列表数据 */
	public <T extends Idable> PaginationList<T> findPagingByExpLike(final T instance, PagingVo pvo, final LinkedHashMap<String,String> orderMap, String [] fieldNames) throws DataAccessException {
		return findPagingByQBC(MatchMode.ANYWHERE, instance, pvo, orderMap, fieldNames, null);
	}

	/**  根据样例数据查询相同属性值的列表数据 */
	public <T> PaginationList<T> findPagingByExpLike(final Idable instance, PagingVo pvo, final LinkedHashMap<String,String> orderMap, String [] fieldNames, Class<T> toBeanClass) throws DataAccessException {
		return findPagingByQBC(MatchMode.ANYWHERE, instance, pvo, orderMap, fieldNames, null);
	}

	public <T extends Idable> PaginationList<T> findPagingByExample(final T instance, PagingVo pvo,final LinkedHashMap<String,String> orderMap, String [] fieldNames) throws DataAccessException {
		return findPagingByQBC(MatchMode.ANYWHERE, instance, pvo, orderMap, fieldNames, null);
	}


	/** 根据示例数据分页查询对象  */
	protected <T> PaginationList<T> findPagingByQBC(final MatchMode matchMode, final Idable instance, PagingVo pvo, final LinkedHashMap<String,String> orderMap, String [] fieldNames, Class<T> toBeanClass) throws DataAccessException {
		PaginationList<T> p = new PaginationList<T>();
		if(null == instance){
			return p;
		}

		if(null == pvo) {
			pvo = new PagingVo();
		}
		Integer pageSize = pvo.getPg_size();
		Integer page = pvo.getPg_idx();

		if(null==pageSize || pageSize < 1 || pageSize > SQLUtil.MAX_QUERY_SIZE){
			pageSize = PaginationList.PAGE_SIZE;
		}
		if(null==page || page<1){
			page = 1;
		}
		int fr = (page - 1) * pageSize;

		Session session = getCurrSession();
		
		CriteriaBuilder builder = session.getCriteriaBuilder();
		CriteriaQuery query = builder.createQuery(null);
		Root root = query.from(instance.getClass());
		
		// 获取实体中所有属性字段
		Set<Field> insFields = ReflectUtil.getDeclaredFields(instance.getClass(), true);

		fillQueryCondition(MatchMode.EXACT, instance, insFields, builder, query, root);
		query.select(builder.count(root.get("id")));
        
		Long size = (Long) session.createQuery(query).getSingleResult();
		int totals = (null==size || size<1) ? 0 :  size.intValue();
		if(totals<1L || fr>totals){return p;}

		restrictQueryField(insFields, builder, query, root, fieldNames, toBeanClass, orderMap);
		
		/* 查询实际业务数据 */
		Query hQuery = session.createQuery(query).setFirstResult(fr).setMaxResults(pageSize);
		
		 if(null != toBeanClass){
			 hQuery.setTupleTransformer(Transformers.aliasToBean(toBeanClass)); 
		 }else if(null!=fieldNames && fieldNames.length>0){
			 hQuery.setTupleTransformer(Transformers.aliasToBean(instance.getClass())); 
		 }
		 
		
		List list = hQuery.getResultList();

		p.setTotalSize(totals);
		p.setPageNum(page);
		p.setPageSize(pageSize);
		p.addAll(list);

		return p;
	}

	public PaginationList findPaginatedList(String hql, List<HibernateParam> params, PagingVo pvo, Boolean readOnly)throws DataAccessException{
		return findPaginatedList(hql, params, pvo, null, readOnly);
	}

	/** Query data by page according to HQL  */
	public PaginationList findPaginatedList(final String hql, List<HibernateParam> params, PagingVo pvo, String countHqlBlock, Boolean readOnly)
			throws DataAccessException {
		PaginationList p = new PaginationList();
		if(StrUtil.isBlankIncNullStr(hql)) {
			return p;
		}
		
		int pageSize = 0;
		int page = 1;
		if(null == pvo) {
			pageSize = SQLUtil.MAX_QUERY_SIZE;
		}else {
			pageSize = pvo.getPg_size();
			page = pvo.getPg_idx();
		}

		if(pageSize < 1 || pageSize > SQLUtil.MAX_QUERY_SIZE){
			pageSize = PaginationList.PAGE_SIZE;
		}
		if(page<1){
			page = 1;
		}
		int fr = (page - 1) * pageSize;

		Session session = null;
		String countHql = null;
		List rsList = null;
		int size = 0;

		if (pageSize == 0) {
			pageSize = PaginationList.PAGE_SIZE;
		}

		if (page < 1) {
			page = 1;
		}

		countHql = this.getCountQuery(hql, countHqlBlock);
		session = this.getCurrSession();

		SelectionQuery countQuery  = fillParams(session.createSelectionQuery(countHql), params);
		if(null == countQuery) {
			size = 0;
		}else {
			if(null!=readOnly && readOnly) {
				countQuery.setReadOnly(true);
			}
			try {
				size = StrUtil.intVal("" + countQuery.uniqueResult());
			}catch(Exception e) {
				if(e instanceof NonUniqueResultException) {
					size = countQuery.list().size();
				}
			}
		}
		if(size<1L || fr>size){return p;}

		try {
			SelectionQuery query = fillParams(session.createSelectionQuery(hql), params);
			if(null == query) {
				return null;
			}
			if(null!=readOnly && readOnly) {
				countQuery.setReadOnly(true);
			}
			query.setFirstResult((page - 1) * pageSize);
			query.setMaxResults(pageSize);
			rsList = query.list();
		} catch (Exception e) {
			e.printStackTrace();
		}

		PaginationList pList = new PaginationList();
		if(null != rsList) {
			pList.addAll(rsList);
		}
		pList.setPageNum(page);
		pList.setTotalSize(size);
		pList.setPageSize(pageSize);
		return pList;
	}


	public PaginationList findPaginatedBySQL(String hql, List<HibernateParam> params, PagingVo pvo, Boolean readOnly)throws DataAccessException{
		return findPaginatedBySQL(hql, params, pvo, null, readOnly);
	}

	/** 根据本地SQL语句查询数据 */
	public PaginationList findPaginatedBySQL(final String sql, List<HibernateParam> params, PagingVo pvo, String countHqlBlock, Boolean readOnly)
			throws DataAccessException {
		PaginationList p = new PaginationList();
		if(StrUtil.isBlankIncNullStr(sql)) {
			return p;
		}
		if(null == pvo) {
			pvo = new PagingVo();
		}
		int pageSize = pvo.getPg_size();
		int page = pvo.getPg_idx();

		if(pageSize < 1 || pageSize > SQLUtil.MAX_QUERY_SIZE){
			pageSize = PaginationList.PAGE_SIZE;
		}
		if(page<1){
			page = 1;
		}
		int fr = (page - 1) * pageSize;

		Session session = getCurrSession();
		String countHql = null;
		List rsList = null;
		int size = 0;

		if (pageSize == 0) {
			pageSize = PaginationList.PAGE_SIZE;
		}

		if (page < 1) {
			page = 1;
		}

		countHql = this.getCountQuery(sql, countHqlBlock);

		NativeQuery countQuery  = fillParams(session.createNativeQuery(countHql), params);
		if(null == countQuery) {
			size = 0;
		}else {
			if(null!=readOnly && readOnly) {
				countQuery.setReadOnly(true);
			}
			try {
				size = StrUtil.intVal("" + countQuery.uniqueResult());
			}catch(Exception e) {
				if(e instanceof NonUniqueResultException) {
					size = countQuery.list().size();
				}
			}
		}
		if(size<1L || fr>size){return p;}

		try {
			NativeQuery query = fillParams(session.createNativeQuery(sql), params);
			if(null == query) {
				return null;
			}
			if(null!=readOnly && readOnly) {
				countQuery.setReadOnly(true);
			}
			query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
			query.setFirstResult((page - 1) * pageSize);
			query.setMaxResults(pageSize);
			rsList = query.list();
		} catch (Exception e) {
			e.printStackTrace();
		}

		PaginationList pList = new PaginationList();
		if(null != rsList) {
			pList.addAll(rsList);
		}
		pList.setPageNum(page);
		pList.setTotalSize(size);
		pList.setPageSize(pageSize);
		return pList;
	}

	

	/**
	 * 填充HQL的Update语句中的参数值
	 * @param <T>
	 * @param hqlQuery
	 * @param params
	 * @return
	 */
	protected <T extends NativeQuery> T fillParams(T hqlQuery, final Collection<HibernateParam> params) {
		if(null == hqlQuery) {
			return null;
		}
		if(null!=params && params.size()>0) {
			for (HibernateParam hp : params) {
				if(StrUtil.NotBlankIgnoreNullStr(hp.getName()) && null!=hp.getVal()) {
					if(hp.getVal() instanceof Object[]) {
						hqlQuery.setParameterList(hp.getName(), (Object[])hp.getVal());
					}else if(hp.getVal() instanceof Collection) {
						hqlQuery.setParameterList(hp.getName(), (Collection)hp.getVal());
					}else {
						hqlQuery.setParameter(hp.getName(), hp.getVal());
					}
				}
			}
		}
		return hqlQuery;
	}
	/**
	 * 填充HQL的Update语句中的参数值
	 * @param <T>
	 * @param hqlQuery
	 * @param params
	 * @return
	 */
	protected <T extends MutationQuery> T fillParams(T hqlQuery, final Collection<HibernateParam> params) {
		if(null == hqlQuery) {
			return null;
		}
		if(null!=params && params.size()>0) {
			for (HibernateParam hp : params) {
				if(StrUtil.NotBlankIgnoreNullStr(hp.getName()) && null!=hp.getVal()) {
					if(hp.getVal() instanceof Object[]) {
						hqlQuery.setParameterList(hp.getName(), (Object[])hp.getVal());
					}else if(hp.getVal() instanceof Collection) {
						hqlQuery.setParameterList(hp.getName(), (Collection)hp.getVal());
					}else {
						hqlQuery.setParameter(hp.getName(), hp.getVal());
					}
				}
			}
		}
		return hqlQuery;
	}
	/**
	 * 填充HQL查询语句中的参数值
	 * @param <T>
	 * @param hqlQuery
	 * @param params
	 * @return
	 */
	protected <T extends SelectionQuery> T fillParams(T hqlQuery, final Collection<HibernateParam> params) {
		if(null == hqlQuery) {
			return null;
		}
		if(null!=params && params.size()>0) {
			for (HibernateParam hp : params) {
				if(StrUtil.NotBlankIgnoreNullStr(hp.getName()) && null!=hp.getVal()) {
					if(hp.getVal() instanceof Object[]) {
						hqlQuery.setParameterList(hp.getName(), (Object[])hp.getVal());
					}else if(hp.getVal() instanceof Collection) {
						hqlQuery.setParameterList(hp.getName(), (Collection)hp.getVal());
					}else {
						hqlQuery.setParameter(hp.getName(), hp.getVal());
					}
				}
			}
		}
		return hqlQuery;
	}

	/**  根据示例对象查询匹配的数据记录条数
	 * @param instance
	 * @param countPropertyName
	 */
	public int findSizeByExpCountById(Idable instance) {
		if(null == instance){
			return 0;
		}
		Session session = getCurrSession();

		CriteriaBuilder builder = session.getCriteriaBuilder();
		CriteriaQuery<Long> query = builder.createQuery(Long.class);
		Root root = query.from(instance.getClass());
		// 获取实体中所有属性字段
		Set<Field> insFields = ReflectUtil.getDeclaredFields(instance.getClass(), true);

		fillQueryCondition(MatchMode.EXACT, instance, insFields, builder, query, root);
		query.select(builder.count(root.get("id")));
        
		Long size = session.createQuery(query).getSingleResult();
		return (null==size) ? 0 : size.intValue();
	}

	/** 根据HQL语句查询符合条件的数据 */
	public long findSizeByHql(final String hql, List<HibernateParam> params) throws DataAccessException {
		if(null==hql){
			return 0;
		}

		SelectionQuery query = fillParams(this.getCurrSession().createSelectionQuery(hql), params);
		List list = query.list();
		query = null;
		if(null==list || list.size()<1){
			return 0L;
		}else{
			if(hql.toLowerCase().indexOf(" count")>0){
				String tmp = hql.toLowerCase().substring(hql.toLowerCase().indexOf(" count"));
				tmp.replaceAll(" ", "");
				if(tmp.indexOf("count(") != -1){
					return StrUtil.longVal(""+list.get(0));
				}else{
					return list.size();
				}
			}
			return list.size();
		}
	}

	private String getCountQuery(String queryStr, String countHqlBlock) {
		if(StrUtil.isBlankIncNullStr(queryStr)) {
			return null;
		}
		String sql = "";
		if (StrUtil.NotBlankIgnoreNullStr(queryStr)) {
			String upperSql = queryStr.toUpperCase();
			int index = upperSql.indexOf("FROM");

			if (index != -1) {

				if(StrUtil.isBlankIncNullStr(countHqlBlock)) {
					countHqlBlock = "*";
				}

				sql = "select count("+ countHqlBlock +") ";

				if(upperSql.indexOf("ORDER BY") != -1){
					sql += queryStr.substring(index, upperSql.indexOf("ORDER BY"));
				}else{
					sql += queryStr.substring(index);
				}

			}
		}
		return sql;
	}

	/**
	 * @param hql
	 * @param params
	 * @return
	 */
	public List findObjects(final String hql, List<HibernateParam> params) {
		return this.findObjects(hql, params, null);
	}

	/**
	 * @param hql
	 * @param params
	 * @return
	 */
	public List findObjects(final String hql, final List<HibernateParam> params, final Integer maxSize) {
		if(StrUtil.isBlankIncNullStr(hql)) {
			return null;
		}
		Session session = this.getCurrSession();
		SelectionQuery query = fillParams(session.createSelectionQuery(hql), params);
		if(null == query) {
			return null;
		}

		if(null!=maxSize && maxSize==SQLUtil.UN_LIMIT_SIZE) {
		}else {
			query.setFirstResult(0);
			if(null==maxSize || maxSize<1 || maxSize>SQLUtil.MAX_QUERY_SIZE) {
				query.setMaxResults(SQLUtil.MAX_QUERY_SIZE);
			}else {
				query.setMaxResults(maxSize);
			}
		}
		return query.list();
	}

	/**
	 * @param hql
	 * @param params
	 * @return
	 */
	public Object findUniqueObject(final String hql, final List<HibernateParam> params) {
		if(StrUtil.isBlankIncNullStr(hql)) {
			return null;
		}
		Session session = this.getCurrSession();
		SelectionQuery query = fillParams(session.createSelectionQuery(hql), params);
		if(null == query) {
			return null;
		}

		return  query.uniqueResult();
	}


	/**保存一个实体对象，根据id修改一个对象 */
	public boolean saveObjAndUpdtIgnoreNullObj(Idable svObj, Idable updtObj) {
		if(null != svObj) {
			this.addOrUpdate(svObj);
		}
		if(null != updtObj) {
			this.updtByIdIgnoreNull(updtObj);
		}
		return true;
	}

	/**保存一批实体对象，根据id修改一个对象 */
	public boolean saveObjsAndUpdtIgnoreNullObj(Collection<Idable> svObjs, Idable updtObj) {
		if(null != svObjs) {
			Iterator<Idable> suIter = svObjs.iterator();
			while(suIter.hasNext()) {
				this.addOrUpdate(suIter.next());
			}
		}
		if(null != updtObj) {
			this.updtByIdIgnoreNull(updtObj);
		}
		return true;
	}

	
	public final Serializable addObj(Idable o) throws DataAccessException {
		if(null == o) {
			return null;
		}
		this.getCurrSession().persist(fillOptInfo(o));
		return o.getId();
	}

	public boolean addObjs(Collection<Idable> addObjs) {
		if(null == addObjs) {
			return false;
		}
		try {
			Session session = this.getCurrSession();
			Iterator<Idable> iter = addObjs.iterator();
			int i=0;
			while(iter.hasNext()) {
				Idable o = iter.next();
				if(null == o) {
					continue;
				}
				session.persist(fillOptInfo(o));
				if(i%100 == 0){
					session.flush();
					session.clear();
					i = -1;
				}
				i++;
			}
			session.flush();
			session.clear();

			return true;
		}catch(Exception e) {
			e.printStackTrace();
			return false;
		}
	}
	/** 在同一个事务中保存和修改一个对象 */
	public boolean addAndUpdt(Idable addObj, Idable updtObj) {
		if(null==addObj || null==updtObj) {
			return false;
		}
		try {
			this.addObj(addObj);
			this.updateObject(updtObj);
			return true;
		}catch(Exception e) {
			e.printStackTrace();
			return false;
		}
	}


	public boolean addOrUpdtObj(Idable... olist) {
		if(null==olist || olist.length<1) {
			return false;
		}
		try{
			for(Idable o : olist) {
				if(null != o) {
					this.addOrUpdate(o);
				}
			}
			return true;
		}catch(Exception nuo){
			nuo.printStackTrace();
			return false;
		}
	}

	public boolean addOrUpdate(Idable o) throws DataAccessException {
		if(null == o) {
			return false;
		}
		o = fillOptInfo(o);
		try{
			if(o instanceof Idable){
				if(StrUtil.isBlankIncNullStr(((Idable) o).getId())) {
					this.getEntityManager().persist(o);
					return true;
				}else {
					Integer version = ((Idable) o).getVersion();
					if(null == version) {
						version = this.findVersionById(o.getClass(), ((Idable) o).getId());
						((Idable) o).setVersion(version);
					}
				}
			}
			this.getCurrSession().merge(o);
			return true;
		}catch(Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	/** 填充当前操作信息 */
	private Idable fillOptInfo(Idable o) {
		if(null == o) {
			return null;
		}
		if(StrUtil.isBlankIncNullStr(o.getId())) {
			o.setId(IdGenerator.Id32());
		}

		String ctime = DateTimeUtil.NowTime();
		if((o instanceof TimeCreateable) && (null == ((TimeCreateable)o).getCreateTime())){
			((TimeCreateable) o).setCreateTime(ctime);
		}
		if(o instanceof TimeEditable) {
			((TimeEditable) o).setEditTime(ctime);
		}
		if(o instanceof OperObj) {
			LgnUserVo luv = CurrLgnUserVo.Get();
			if(null != luv && null!=luv.getUserId()) {
				if(StrUtil.isBlankIncNullStr(((OperObj)o).getCreatorId())){
					((OperObj) o).setCreatorId(luv.getUserId());
					((OperObj) o).setCreatorName(luv.getUserName());
				}
				((OperObj) o).setEditorId(luv.getUserId());
				((OperObj) o).setEditorName(luv.getUserName());
			}
		}
		return o;
	}

	public boolean addOrUpdtObjs(Collection<Idable> addAndObjs) {
		if(null == addAndObjs) {
			return false;
		}
		Iterator<Idable> iter = addAndObjs.iterator();
		while(iter.hasNext()) {
			this.addOrUpdate(iter.next());
		}
		return true;
	}

	public boolean addAndUpdtObjs(Collection<Idable> addObjs, Idable... updtObjs) {
		if(null != addObjs) {
			Iterator<Idable> suIter = addObjs.iterator();
			while(suIter.hasNext()) {
				this.addObj(suIter.next());
			}
		}
		this.updateObject(updtObjs);
		return true;
	}

	public boolean addAndUpdtObjs(Collection<Idable> addObjs, Collection<Idable> updtObjs) {
		if(null != addObjs) {
			Iterator<Idable> suIter = addObjs.iterator();
			while(suIter.hasNext()) {
				this.addObj(suIter.next());
			}
		}
		if(null != updtObjs) {
			Iterator<Idable> updtIter = updtObjs.iterator();
			while(updtIter.hasNext()) {
				this.updateObject(updtIter.next());
			}
		}
		return true;
	}

	public boolean addAndUpdtIgnoreNullObjs(Collection<Idable> addObjs, Collection<Idable> updtObjs) {
		if(null != addObjs) {
			Iterator<Idable> suIter = addObjs.iterator();
			while(suIter.hasNext()) {
				this.addObj(suIter.next());
			}
		}
		if(null != updtObjs) {
			Iterator<Idable> updtIter = updtObjs.iterator();
			while(updtIter.hasNext()) {
				this.updtByIdIgnoreNull(updtIter.next());
			}
		}
		return true;
	}
	public boolean addAndUpdtIgnoreNullObj(Idable addObj, Idable updtObj) {
		if(null != addObj) {
			this.addObj(addObj);
		}
		if(null != updtObj) {
			this.updtByIdIgnoreNull(updtObj);
		}
		return true;
	}

	public boolean addOrUpdtObjsAndDels(Collection<Idable> addUpdtObjs, Collection dels) {
		if(null != addUpdtObjs) {
			Iterator<Idable> suIter = addUpdtObjs.iterator();
			while(suIter.hasNext()) {
				this.addOrUpdate(suIter.next());
			}
		}
		if(null != dels) {
			this.deleteEntitys(dels);
		}
		return true;
	}

	
	/** Batch delete persistent objects */
	public void deleteEntitys(Collection entities) throws DataAccessException {
		if(null!=entities && entities.size()>0) {
			Session session = getCurrSession();
			for(Object obj : entities) {
				session.delete(obj);
			}
		}
	}

	/** Delete a single persistent object */
	public void deleteEntity(Object entity) throws DataAccessException {
		if(null != entity) {
			getCurrSession().delete(entity);
		}
	}

	/** Mark logical delete data */

	public int execUpdtHql(final String hql,Collection<HibernateParam> params){
		if(StrUtil.isBlankIncNullStr(hql)) {
			return 0;
		}
		MutationQuery query = fillParams(getCurrSession().createMutationQuery(hql), params);
		if(null != query){
			return query.executeUpdate();
		}else {
			return 0;
		}
	}

	public final boolean updateObjs(Collection<Idable> olist) throws DataAccessException {
		if(null==olist || olist.size()<1) {
			return false;
		}
		try{
			for(Idable o : olist) {
				if(null != o) {
					this.getCurrSession().update(fillOptInfo(o));
				}
			}
			return true;
		}catch(Exception nuo){
			nuo.printStackTrace();
			return false;
		}
	}

	/** 开启独立的一个新的更新数据的事务
	 * <br/>某些事务需要单独处理，比如更新调用第三方接口的统计，这个操作不能跟本程序的事务混为一起 */
	@Transactional(propagation= Propagation.NOT_SUPPORTED, readOnly=false)
	public boolean newUpdtTransactional(Idable obj) {
		if(null == obj) {
			return false;
		}
		try {
			Session session = this.getSessionFactory().openSession();
			Transaction transaction = session.beginTransaction();
			session.update(fillOptInfo(obj));
			session.flush();
			transaction.commit();
			session.close();
			return true;
		}catch(Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	public void evictObj(Object obj) throws DataAccessException {
		if(null != obj){
			this.getCurrSession().evict(obj);
		}
	}

	public <Idable> Idable findObjById(Class<? extends Idable> clazz, Serializable id) throws DataAccessException {
		if(null==clazz || null==id || "".equals(id)){
			return null;
		}
		Idable t = this.getCurrSession().get(clazz, id);
		if(null != t) {
			this.getCurrSession().evict(t);
		}
		return t;
	}

	/** 根据ID查询此数据的数据版本号 */
	public IdVersionVo findIdVersionVoById(Class clazz, String id) {
		Integer version = findVersionById(clazz, id);
		if(null == version) {
			return null;
		}
		return new IdVersionVo(id, version);
	}

	/** 根据ID查询此数据的数据版本号 */
	public Integer findVersionById(Class clazz, String id) {
		if(null==clazz || StrUtil.isBlankIncNullStr(id)){return null;}

		StringBuffer hql = new StringBuffer(" select version from ")
				.append(clazz.getCanonicalName()).append(" where id=:id ");
		
		List<HibernateParam> params = new ArrayList<HibernateParam>();
        params.add(new HibernateParam("id", id));

		/* 查询实际业务数据 */
		SelectionQuery query = getCurrSession().createSelectionQuery(hql.toString());
		for(HibernateParam pr : params){
			query.setParameter(pr.getName(), pr.getVal());
		}
		query.setMaxResults(1);

		return (Integer)query.uniqueResult();
	}


	/** 开启独立的一个新的更新数据的事务
	 * <br/>某些事务需要单独处理，比如更新调用第三方接口的统计，这个操作不能跟本程序的事务混为一起 */
	@Transactional(propagation= Propagation.NOT_SUPPORTED, readOnly=false)
	public Serializable newAddTransactional(Idable obj) {
		if(null == obj) {
			return false;
		}
		Session session = this.getSessionFactory().openSession();
		Transaction transaction = session.beginTransaction();
		session.persist(fillOptInfo(obj));
		session.flush();
		transaction.commit();
		session.close();
		return obj.getId();
	}

	public final boolean updateObject(Idable... olist) throws DataAccessException {
		if(null==olist || olist.length<1) {
			return false;
		}
		try{
			for(Idable o : olist) {
				this.getCurrSession().update(fillOptInfo(o));
			}
			return true;
		}catch(Exception nuo){
			nuo.printStackTrace();
			return false;
		}
	}

	public boolean addAndUpdtObjsAndDels(Collection<Idable> addObjs,Collection updtObjs, Collection dels, Set<String> afterHqls) {
		if(null != dels && dels.size()>0) {
			/*先删除，后新增，兼容先删除原数据后保存新的记录 */
			this.deleteEntitys(dels);
		}
		if(null != addObjs && addObjs.size()>0) {
			Iterator<Idable> suIter = addObjs.iterator();
			while(suIter.hasNext()) {
				this.addObj(suIter.next());
			}
		}
		if(null != updtObjs && updtObjs.size()>0) {
			Iterator<Idable> suIter = updtObjs.iterator();
			while(suIter.hasNext()) {
				this.updateObject(suIter.next());
			}
		}
		if(null != afterHqls && afterHqls.size()>0) {
			Iterator<String> suIter = afterHqls.iterator();
			while(suIter.hasNext()) {
				this.execUpdtHql(suIter.next(), null);
			}
		}


		return true;
	}

	/** 注意：此方法为物理删除，数据删除后将无法恢复；
	 *  根据ID值 删除数据对象  */
	public int delObjById(Class clazz, Serializable id) {
		if(null==clazz || null==id || StrUtil.isBlankIncNullStr(id.toString())) {
			return 0;
		}

		Entity ety = (Entity) clazz.getAnnotation(Entity.class);
		if(null == ety) {
			System.err.println("未获取到有效的持久化类，持久化类需有@Entity注解  ");
			return 0;
		}
		String etyName = ety.name();
		if(StrUtil.isBlankIncNullStr(etyName)) {
			/** 如果没有明确设置实体类名，则默认会使用类名称 */
			etyName = clazz.getSimpleName();
		}

		Session session = getCurrSession();

		String deleteChildrenSql="delete from "+ etyName +" where id =:delId";
		return session.createMutationQuery(deleteChildrenSql).setParameter("delId", id).executeUpdate();
	}

	/** 注意：此方法为物理删除，数据删除后将无法恢复；
	 *  根据ID值 集合 删除 数据列表 */
	public int delObjByIds(Class clazz, Collection<String> delIds) {
		if(null==clazz || null==delIds || delIds.size()<1) {
			return 0;
		}

		Session session = getCurrSession();

		Entity ety = (Entity) clazz.getAnnotation(Entity.class);
		if(null == ety) {
			System.err.println("未获取到有效的持久化类，持久化类需有@Entity注解  ");
			return 0;
		}
		String etyName = ety.name();
		if(StrUtil.isBlankIncNullStr(ety.name())) {
			/** 如果没有明确设置实体类名，则默认会使用类名称 */
			etyName = clazz.getSimpleName();
		}
		String deleteChildrenSql="delete from "+ etyName +" where id in (:delIds)";
		return session.createMutationQuery(deleteChildrenSql).setParameter("delIds", delIds).executeUpdate();
	}

	/** 根据示例查找对象，并将查找的数据放到toBeanClass实例中 */
	public <T>List<T> findListByExample(Idable instance, Integer maxQuerySize, final LinkedHashMap<String,String> orderMap, Class<T> toBeanClass, String[] fieldNames) {
		if(null==instance) {
			return new ArrayList<T>();
		}
		
		Session session = getCurrSession();
		
		CriteriaBuilder builder = session.getCriteriaBuilder();
		CriteriaQuery query = builder.createQuery(null);
		Root root = query.from(instance.getClass());

		// 获取实体中所有属性字段
		Set<Field> insFields = ReflectUtil.getDeclaredFields(instance.getClass(), true);
		fillQueryCondition(MatchMode.EXACT, instance, insFields, builder, query, root);
		restrictQueryField(insFields, builder, query, root, fieldNames, toBeanClass, orderMap);
		
		/* 查询实际业务数据 */
		Query hQuery = session.createQuery(query).setFirstResult(0).setMaxResults(SQLUtil.MAX_QUERY_SIZE);
		if(null != toBeanClass){
			hQuery.setTupleTransformer(Transformers.aliasToBean(toBeanClass));
		}else if(null!=fieldNames && fieldNames.length>0){
			hQuery.setTupleTransformer(Transformers.aliasToBean(instance.getClass()));
		}
		
		List<T> list  = hQuery.getResultList();


		return list;
	}



	public List findListBySQL(String sql, Map<String, Object> params) {
		NativeQuery query = this.getCurrSession().createNativeQuery(sql);
		for (Map.Entry<String, Object> param : params.entrySet()) {
			query.setParameter(param.getKey(), param.getValue());
		}
		query.setCacheMode(CacheMode.IGNORE);
		return query.getResultList();
	}

	
	/** 填充查询条件；注意：内部使用，没有对数据进行非空等判断 */
	protected CriteriaQuery fillQueryCondition(MatchMode matchMode, final Idable instance, Set<Field> insFields, CriteriaBuilder builder, CriteriaQuery query, Root root) {

		List<Predicate> predicateList = new ArrayList<>();

		if(null==matchMode || MatchMode.EXACT.equals(matchMode)) {
			for (Field field : insFields) {
		        // 获取属性字段类型
		   		String canonicalName = field.getType().getCanonicalName();
		   		if(Modifier.isStatic(field.getModifiers())) {
		   			/* 静态变量不作为查询条件 */
		   			continue;
		   		}
		   		 // 获取字段值
		         Object fieldValue = ReflectUtil.getFieldValue(instance, field);
		         if(ObjectUtils.isEmpty(fieldValue)) {
			   		/* 空置不作为查询条件 */
		        	 continue;
		         }

		         predicateList.add(builder.equal(root.get(field.getName()), fieldValue));
		         System.out.println("字段类型：" + canonicalName);
		         System.out.println(field.getName() + "值：" + fieldValue);
		    }
		}else{
			for (Field field : insFields) {
		        // 获取属性字段类型
		   		String canonicalName = field.getType().getCanonicalName();
		   		if(Modifier.isStatic(field.getModifiers())) {
		   			/* 静态变量不作为查询条件 */
		   			continue;
		   		}
		   		 // 获取字段值
		         Object fieldValue = ReflectUtil.getFieldValue(instance, field);
		         if(ObjectUtils.isEmpty(fieldValue)) {
			   		/* 空置不作为查询条件 */
		        	 continue;
		         }
		         if("id".equals(field.getName())) {
		        	 predicateList.add(builder.equal(root.get("id"), fieldValue));
		         }else {
		        	/*  数据类型判断 */
		        	if (Number.class.isAssignableFrom(field.getType())) {
			        	 System.out.println("条件字段是数字类型： " + field.getGenericType().getTypeName());
			        	 predicateList.add(builder.equal(root.get(field.getName()),fieldValue));
	        	    } else if (Boolean.class.isAssignableFrom(field.getType())) {
			        	 predicateList.add(builder.equal(root.get(field.getName()),fieldValue));
	        	    } else if (Character.class.isAssignableFrom(field.getType())) {
			        	 predicateList.add(builder.like(root.get(field.getName()), matchMode.toMatchString((String)fieldValue)));
	        	    } else if (String.class.isAssignableFrom(field.getType())) {
			        	 predicateList.add(builder.like(root.get(field.getName()), matchMode.toMatchString((String)fieldValue)));
	        	    }
		        	 
		         }
		         
		         System.out.println("字段类型：" + canonicalName);
		         System.out.println(field.getName() + "值：" + fieldValue);
		    }
		}
		

        Predicate[] predicates = predicateList.toArray(new Predicate[predicateList.size()]);
        query.where(predicates);//where条件加上
		return query;
	}

	/** 限定查询字段与排序字段 */
	protected CriteriaQuery restrictQueryField(Set<Field> insFields, CriteriaBuilder builder, CriteriaQuery query, Root root,
			String[] fieldNames, Class toBeanClass, final LinkedHashMap<String, String> orderMap) {

		List<Selection> fields = new ArrayList();
		if(null!=fieldNames && fieldNames.length>0) {
			for(String fname : fieldNames) {
				fields.add(root.get(fname).alias(fname));
			}
			query.multiselect(fields.toArray(new Selection[fields.size()]));
		}else if(null != toBeanClass){
			/* 没有指定字段,则使用toBeanClass与instance字段的交集 */
			Set<String> insf = insFields.stream().map(Field::getName).collect(Collectors.toSet());
			List<String> fnames = ReflectUtil.getDeclaredFields(toBeanClass, true).stream()
					.map(Field::getName).filter(f ->insf.contains(f)).collect(Collectors.toList());
			for(String fname : fnames) {
				fields.add(root.get(fname).alias(fname));
			}
			query.multiselect(fields.toArray(new Selection[fields.size()]));
		}else {
			/** 直接查询*/
			query.select(root);
		}

		if(null!=orderMap && orderMap.size()>0){
			Set<String> pKeys =  orderMap.keySet();
			boolean noId = true;
			for(String propertyName : pKeys){
				if(null!=propertyName && !"".equals(propertyName.trim())){
					if("desc".equalsIgnoreCase(orderMap.get(propertyName))){
						query.orderBy(builder.desc(root.get(propertyName)));
					}else{
						query.orderBy(builder.asc(root.get(propertyName)));
					}
					if("id".equalsIgnoreCase(propertyName)) {
						noId = false;
					}
				}
			}
			if(noId) {
				query.orderBy(builder.desc(root.get("id")));
			}
		}else{
			query.orderBy(builder.desc(root.get("id")));
		}
		
		return query;
	}

}